home *** CD-ROM | disk | FTP | other *** search
/ Practical Internet 2002 February / Practical Internet February 2002.iso / pc / Software / Browsing / httrack-3.09e2.exe / {app} / src / htsback.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-11-07  |  83.0 KB  |  2,191 lines

  1. /* ------------------------------------------------------------ */
  2. /*
  3. HTTrack Website Copier, Offline Browser for Windows and Unix
  4. Copyright (C) Xavier Roche and other contributors
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20.  
  21. Important notes:
  22.  
  23. - We hereby ask people using this source NOT to use it in purpose of grabbing
  24. emails addresses, or collecting any other private information on persons.
  25. This would disgrace our work, and spoil the many hours we spent on it.
  26.  
  27.  
  28. Please visit our Website: http://www.httrack.com
  29. */
  30.  
  31.  
  32. /* ------------------------------------------------------------ */
  33. /* File: httrack.c subroutines:                                 */
  34. /*       backing system (multiple socket download)              */
  35. /* Author: Xavier Roche                                         */
  36. /* ------------------------------------------------------------ */
  37.  
  38. #include "htsback.h"
  39.  
  40. /* specific definitions */
  41. #include "htsbase.h"
  42. #include "htsnet.h"
  43. #include "htsthread.h"
  44. #include <stdio.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47. /* END specific definitions */
  48.  
  49. //#if HTS_WIN
  50. #include "htsftp.h"
  51. #if HTS_USEZLIB
  52. #include "htszlib.h"
  53. #endif
  54. //#endif
  55.  
  56. #if HTS_WIN
  57. #ifndef __cplusplus
  58. // DOS
  59. #include <process.h>    /* _beginthread, _endthread */
  60. #endif
  61. #else
  62. #endif
  63.  
  64. #undef test_flush
  65. #define test_flush if (opt->flush) { fflush(opt->log); fflush(opt->errlog); }
  66.  
  67. #define VT_CLREOL       "\33[K"
  68.  
  69.  
  70. // ---
  71. // routines de backing
  72. // retourne l'index d'un lien dans un tableau de backing
  73. int back_index(lien_back* back,int back_max,char* adr,char* fil,char* sav) {
  74.   register int i=0;
  75.   register int index=-1;
  76.   while( i<back_max ) {
  77.     if (back[i].status>=0)    // rΘception OU prΩt
  78.       if (strfield2(back[i].url_adr,adr)) {
  79.         if (strcmp(back[i].url_fil,fil)==0) {
  80.           if (index==-1)    /* first time we meet, store it */
  81.             index=i;
  82.           else if (strcmp(back[i].url_sav,sav)==0) {  /* oops, check sav too */
  83.             index=i;
  84.             return index;
  85.           }
  86.         }
  87.       }
  88.     i++;
  89.   }
  90.   return index;
  91. }
  92.  
  93. // nombre d'entrΘes libres dans le backing
  94. int back_available(lien_back* back,int back_max) {
  95.   int i;
  96.   int nb=0;
  97.   for(i=0;i<back_max;i++)
  98.     if (back[i].status==-1)     /* libre */
  99.       nb++;
  100.   return nb;
  101. }
  102.  
  103. // retourne estimation de la taille des html et fichiers stockΘs en mΘmoire
  104. LLint back_incache(lien_back* back,int back_max) {
  105.   int i;
  106.   LLint sum=0;
  107.   for(i=0;i<back_max;i++)
  108.     if (back[i].status!=-1)
  109.       if (back[i].r.adr)       // ne comptabilier que les blocs en mΘmoire
  110.         sum+=max(back[i].r.size,back[i].r.totalsize);
  111.   return sum;
  112. }
  113.  
  114. // le lien a-t-il ΘtΘ mis en backing?
  115. HTS_INLINE int back_exist(lien_back* back,int back_max,char* adr,char* fil,char* sav) {
  116.   return (back_index(back,back_max,adr,fil,sav)>=0);
  117. }
  118.  
  119. // nombre de sockets en tΓche de fond
  120. int back_nsoc(lien_back* back,int back_max) {
  121.   int n=0;
  122.   int i;
  123.   for(i=0;i<back_max;i++)
  124.     if (back[i].status>0)    // rΘception uniquement
  125.       n++;
  126.  
  127.   return n;
  128. }
  129.  
  130. // objet (lien) tΘlΘchargΘ ou transfΘrΘ depuis le cache
  131. //
  132. // fermer les paramΦtres de transfert,
  133. // et notamment vΘrifier les fichiers compressΘs (dΘcompresser), callback etc.
  134. int back_finalize(httrackp* opt,cache_back* cache,lien_back* back,int p) {
  135.   if (
  136.       (back[p].status == 0)      // ready
  137.       &&
  138.       (!back[p].testmode)        // not test mode
  139.       &&
  140.       (back[p].r.statuscode>0)   // not internal error
  141.       ) {
  142.     
  143.     /* dΘcompression */
  144. #if HTS_USEZLIB
  145.     if (back[p].r.compressed) {
  146.       if ( (back[p].r.adr) && (back[p].r.size) ) {
  147.         // stats
  148.         back[p].compressed_size=back[p].r.size;
  149.         // en mΘmoire -> passage sur disque
  150.         if (!back[p].r.is_write) {
  151.           back[p].tmpfile[0]='\0';
  152.           strcpy(back[p].tmpfile,tempnam(NULL,"httrZ"));
  153.           if (back[p].tmpfile[0]) {
  154.             back[p].r.out=fopen(back[p].tmpfile,"wb");
  155.             if (back[p].r.out) {
  156.               if ((INTsys)fwrite(back[p].r.adr,1,(INTsys)back[p].r.size,back[p].r.out) != back[p].r.size) {
  157.                 back[p].r.statuscode=-1;
  158.                 strcpy(back[p].r.msg,"Write error when decompressing");
  159.               }
  160.             } else {
  161.               back[p].tmpfile[0]='\0';
  162.               back[p].r.statuscode=-1;
  163.               strcpy(back[p].r.msg,"Open error when decompressing");
  164.             }
  165.           }
  166.         }
  167.         // fermer fichier sortie
  168.         if (back[p].r.out!=NULL) {
  169.           fclose(back[p].r.out);
  170.           back[p].r.out=NULL;
  171.         }
  172.         // dΘcompression
  173.         if (back[p].tmpfile[0] && back[p].url_sav[0]) {
  174.           LLint size;
  175.           filecreate(back[p].url_sav);      // filenote & co
  176.           if ((size = hts_zunpack(back[p].tmpfile,back[p].url_sav))>=0) {
  177.             back[p].r.size=back[p].r.totalsize=size;
  178.             // fichier -> mΘmoire
  179.             if (!back[p].r.is_write) {
  180.               back[p].r.adr=readfile(back[p].url_sav);
  181.               if (!back[p].r.adr) {
  182.                 back[p].r.statuscode=-1;
  183.                 strcpy(back[p].r.msg,"Read error when decompressing");
  184.               }
  185.               remove(back[p].url_sav);
  186.             }
  187.           }
  188.           remove(back[p].tmpfile);
  189.         }
  190.         // stats
  191.         HTS_STAT.total_packed+=back[p].compressed_size;
  192.         HTS_STAT.total_unpacked+=back[p].r.size;
  193.         HTS_STAT.total_packedfiles++;
  194.         // unflag
  195.       }
  196.       back[p].r.compressed=0;
  197.     }
  198. #endif
  199.     
  200.     /* Stats */
  201.     if (back[p].r.size>=0) {
  202.       if (back[p].r.statuscode==200) {
  203.         HTS_STAT.stat_bytes+=back[p].r.size;
  204.         HTS_STAT.stat_files++;
  205.         if ( (!back[p].r.notmodified) && (opt->is_update) ) { 
  206.           HTS_STAT.stat_updated_files++;       // page modifiΘe
  207.           if (opt->log!=NULL) {
  208.             fspc(opt->log,"info"); fprintf(opt->log,"engine: transfer-status: link updated: %s%s -> %s"LF,back[p].url_adr,back[p].url_fil,back[p].url_sav);
  209.             test_flush;
  210.           }
  211.         } else {
  212.           if ( (opt->debug>0) && (opt->log!=NULL) ) {
  213.             fspc(opt->log,"info"); fprintf(opt->log,"engine: transfer-status: link recorded: %s%s -> %s"LF,back[p].url_adr,back[p].url_fil,back[p].url_sav);
  214.             test_flush;
  215.           }
  216.         }
  217.       } else {
  218.         if ( (opt->debug>0) && (opt->log!=NULL) ) {
  219.           fspc(opt->log,"info"); fprintf(opt->log,"engine: transfer-status: link error (%d, '%s'): %s%s"LF,back[p].r.statuscode,back[p].r.msg,back[p].url_adr,back[p].url_fil);
  220.           test_flush;
  221.         }
  222.       }
  223.     }
  224.     
  225.     /* Cache */
  226.     cache_mayadd(opt,cache,&back[p].r,back[p].url_adr,back[p].url_fil,back[p].url_sav);
  227.       
  228.     // status finished callback
  229. #if HTS_ANALYSTE
  230.     hts_htmlcheck_xfrstatus(&back[p]);
  231. #endif
  232.     return 0;
  233.   }
  234.   return -1;
  235. }
  236.  
  237.  
  238. // effacer entrΘe
  239. int back_delete(lien_back* back,int p) {
  240.   if (p>=0) {    // on sait jamais..
  241.     // VΘrificateur d'intΘgritΘ
  242.     #if DEBUG_CHECKINT
  243.     _CHECKINT(&back[p],"Appel back_delete")
  244.     #endif
  245. #if HTS_DEBUG_CLOSESOCK
  246.     char info[256];
  247.     sprintf(info,"back_delete: #%d\n",p);
  248.     DEBUG_W2(info);
  249. #endif
  250.  
  251.     // LibΘrer tous les sockets, handles, buffers..
  252.     if (back[p].r.soc!=INVALID_SOCKET) {
  253. #if HTS_DEBUG_CLOSESOCK
  254.       DEBUG_W("back_delete: deletehttp\n");
  255. #endif
  256.       deletehttp(&back[p].r);
  257.       back[p].r.soc=INVALID_SOCKET;
  258.     }
  259.     if (back[p].r.adr!=NULL) {  // reste un bloc α dΘsallouer
  260.       freet(back[p].r.adr);
  261.       back[p].r.adr=NULL;
  262.     }
  263.     if (back[p].chunk_adr!=NULL) {  // reste un bloc α dΘsallouer
  264.       freet(back[p].chunk_adr);
  265.       back[p].chunk_adr=NULL;
  266.       back[p].chunk_size=0;
  267.       back[p].is_chunk=0;
  268.     }
  269.     if (back[p].r.is_file) {  // fermer fichier entrΘe
  270.       if (back[p].r.fp!=NULL) {
  271.         fclose(back[p].r.fp);
  272.         back[p].r.fp=NULL;
  273.       }
  274.     }
  275.     if (back[p].r.is_write) {     // ecriture directe
  276.  
  277.       /* fichier de sortie */
  278.       if (back[p].r.out!=NULL) {  // fermer fichier sortie
  279.         fclose(back[p].r.out);
  280.         back[p].r.out=NULL;
  281.       }
  282.       
  283.       /* Θcrire date "remote" */
  284.       if (strnotempty(back[p].url_sav))          // normalement existe si on a un fichier de sortie
  285.       if (strnotempty(back[p].r.lastmodified))   // last-modified existe
  286.       if (fexist(back[p].url_sav))          // ainsi que le fichier
  287.         set_filetime_rfc822(back[p].url_sav,back[p].r.lastmodified);
  288.  
  289.       /* executer commande utilisateur aprΦs chargement du fichier */
  290.       usercommand(0,NULL,back[p].url_sav);
  291.       back[p].r.is_write=0;
  292.     }
  293.     
  294.     // Tout nettoyer
  295.     bzero((char *)(&back[p]),sizeof(lien_back));  
  296.     back[p].r.soc=INVALID_SOCKET; back[p].r.location=back[p].location_buffer;
  297.     
  298.     // Le plus important: libΘrer le champ
  299.     back[p].status=-1;
  300.   }
  301.   return 0;
  302. }
  303.  
  304. /* Space left on backing stack */
  305. int back_stack_available(lien_back* back,int back_max) {
  306.   int p=0,n=0;
  307.   for( ; p < back_max ; p++ )
  308.     if ( back[p].status == -1 )
  309.       n++;
  310.   return n;
  311. }
  312.  
  313. // ajouter un lien en backing
  314. int back_add(lien_back* back,int back_max,httrackp* opt,cache_back* cache,char* adr,char* fil,char* save,char* referer_adr,char* referer_fil,int test,short int* pass2_ptr) {
  315.   int p=0;
  316.  
  317.   // vΘrifier cohΘrence de adr et fil (non vide!)
  318.   if (strnotempty(adr)==0) {
  319.     if ((opt->debug>1) && (opt->errlog!=NULL)) {
  320.       fspc(opt->errlog,"debug"); fprintf(opt->errlog,"error: adr is empty for back_add"LF);
  321.     }
  322.     return -1;    // erreur!
  323.   }
  324.   if (strnotempty(fil)==0) {
  325.     if ((opt->debug>1) && (opt->errlog!=NULL)) {
  326.       fspc(opt->errlog,"debug"); fprintf(opt->errlog,"error: fil is empty for back_add"LF);
  327.     }
  328.     return -1;    // erreur!
  329.   }
  330.   // FIN vΘrifier cohΘrence de adr et fil (non vide!)
  331.  
  332.   // rechercher emplacement
  333.   while((p<back_max) && back[p].status!=-1) p++;
  334.   if (back[p].status==-1) {    // ok on a de la place
  335.     back[p].send_too[0]='\0';  // Θventuels paramΦtres supplΘmentaires α transmettre au serveur
  336.  
  337.     // ne sert α rien normalement
  338.     if (back[p].r.soc!=INVALID_SOCKET) {
  339. #if HTS_DEBUG_CLOSESOCK
  340.       DEBUG_W("back_add: deletehttp\n");
  341. #endif
  342.       deletehttp(&back[p].r);
  343.     }
  344.  
  345.     // effacer r
  346.     bzero((char*) &(back[p].r), sizeof(htsblk)); back[p].r.soc=INVALID_SOCKET; back[p].r.location=back[p].location_buffer;
  347.  
  348.     // crΘer entrΘe
  349.     strcpy(back[p].url_adr,adr);
  350.     strcpy(back[p].url_fil,fil);
  351.     strcpy(back[p].url_sav,save);
  352.     back[p].pass2_ptr=pass2_ptr;
  353.     // copier referer si besoin
  354.     strcpy(back[p].referer_adr,"");
  355.     strcpy(back[p].referer_fil,"");
  356.     if ((referer_adr) && (referer_fil)) {       // existe
  357.       if ((strnotempty(referer_adr)) && (strnotempty(referer_fil))) {   // non vide
  358.         if (referer_adr[0]!='!') {    // non dΘtruit
  359.           if (strcmp(referer_adr,"file://")) {      // PAS file://
  360.             if (strcmp(referer_adr,"primary")) {      // pas referer 1er lien
  361.               strcpy(back[p].referer_adr,referer_adr);
  362.               strcpy(back[p].referer_fil,referer_fil);
  363.             }
  364.           }
  365.         }
  366.       }
  367.     }
  368.     // sav ne sert α rien pour le moment
  369.     back[p].r.size=0;                   // rien n'a encore ΘtΘ chargΘ
  370.     back[p].r.soc=INVALID_SOCKET;       // pas de socket
  371.     back[p].r.adr=NULL;                 // pas de bloc de mΘmoire
  372.     back[p].r.is_write=0;               // α priori stockage en mΘmoire
  373.     back[p].maxfile_html=opt->maxfile_html;
  374.     back[p].maxfile_nonhtml=opt->maxfile_nonhtml;
  375.     back[p].testmode=test;              // mode test?
  376.     if (!opt->http10)                 // option "forcer 1.0" dΘsactivΘe
  377.       back[p].http11=1;               // autoriser http/1.1
  378.     back[p].head_request=0;
  379.     if (strcmp(back[p].url_sav,BACK_ADD_TEST)==0)    // HEAD
  380.       back[p].head_request=1;
  381.     else if (strcmp(back[p].url_sav,BACK_ADD_TEST2)==0)    // test en GET
  382.       back[p].head_request=2;       // test en get
  383.  
  384.     
  385.     /* Stop requested - abort backing */
  386.     if (opt->state.stop) {
  387.       back[p].r.statuscode=-1;        // fatal
  388.       strcpy(back[p].r.msg,"mirror stopped by user");
  389.       back[p].status=0;  // terminΘ
  390.       if ((opt->debug>0) && (opt->log!=NULL)) {
  391.         fspc(opt->log,"warning"); fprintf(opt->log,"File not added due to mirror cancel: %s%s",adr,fil); test_flush;
  392.       }            
  393.       return 0;
  394.     }
  395.  
  396.  
  397.     // tester cache
  398.     if ((strcmp(adr,"file://"))           /* pas fichier */
  399.       && ( (!test) || (cache->type==1) )   /* cache prioritaire, laisser passer en test! */
  400.       && ( (strnotempty(save)) || (strcmp(fil,"/robots.txt")==0) ) ) {  // si en test on ne doit pas utiliser le cache sinon telescopage avec le 302..
  401.       //if ((!test) && (strcmp(adr,"file://")) 
  402.       //if ((!test) && (strncmp(adr,"ftp://",6)) && (strcmp(adr,"file://")) 
  403. #if HTS_FAST_CACHE
  404.       int hash_pos;
  405.       int hash_pos_return=0;
  406. #else
  407.       char* a=NULL;
  408. #endif
  409. #if HTS_FAST_CACHE
  410.       if (cache->hashtable) { 
  411. #else
  412.       if (cache->use) { 
  413. #endif
  414.         char buff[HTS_URLMAXSIZE*4];
  415. #if HTS_FAST_CACHE
  416.         strcpy(buff,adr); strcat(buff,fil);
  417.         hash_pos_return=inthash_read((inthash)cache->hashtable,buff,(long int*)&hash_pos);
  418. #else
  419.         buff[0]='\0'; strcat(buff,"\n"); strcat(buff,adr); strcat(buff,"\n"); strcat(buff,fil); strcat(buff,"\n");
  420.         a=strstr(cache->use,buff);
  421. #endif
  422.         
  423.         // Ok, notΘ en cache->. mais bien prΘsent dans le cache ou sur disque?
  424. #if HTS_FAST_CACHE
  425.         if (hash_pos_return) {
  426. #else
  427.         if (a) {
  428. #endif
  429.           if (!test) {      // non mode test
  430. #if HTS_FAST_CACHE
  431.             int pos=hash_pos;
  432. #else
  433.             int pos=-1;
  434.             a+=strlen(buff);
  435.             sscanf(a,"%d",&pos);    // lire position
  436. #endif
  437.             if (pos<0) {    // pas de mise en cache data, vΘrifier existence
  438.               if (fsize(antislash(save)) <= 0) {  // fichier existe pas ou est vide!
  439. #if HTS_FAST_CACHE
  440.                 hash_pos_return=0;
  441. #else
  442.                 a=NULL;    
  443. #endif
  444.                 // dΘvalider car non prΘsent sur disque dans structure originale!!!
  445.                 // sinon, le fichier est ok α priori, mais on renverra un if-modified-since pour
  446.                 // en Ωtre s√r
  447.                 if (opt->norecatch) {              // tester norecatch
  448.                   if (!fexist(antislash(save))) {  // fichier existe pas mais dΘclarΘ: on l'a effacΘ
  449.                     FILE* fp=fopen(antislash(save),"wb");
  450.                     if (fp) fclose(fp);
  451.                     if (opt->log!=NULL) {
  452.                       fspc(opt->log,"warning"); fprintf(opt->log,"File must have been erased by user, ignoring: %s%s"LF,back[p].url_adr,back[p].url_fil); test_flush;
  453.                     }
  454.                   }
  455.                 }
  456.               }
  457.             }
  458.           }
  459.         }
  460.         //
  461.       } else
  462. #if HTS_FAST_CACHE
  463.         hash_pos_return=0;
  464. #else
  465.         a=NULL;
  466. #endif
  467.  
  468.       // Existe pas en cache, ou bien pas de cache prΘsent
  469. #if HTS_FAST_CACHE
  470.       if (hash_pos_return) {  // OK existe en cache (et donnΘes aussi)!
  471. #else
  472.       if (a!=NULL) {  // OK existe en cache (et donnΘes aussi)!
  473. #endif
  474.         if (cache->type==1) {   // cache prioritaire (pas de test if-modified..)
  475.                                // dans ce cas on peut Θgalement lire des rΘponses cachΘes comme 404,302... 
  476.           // lire dans le cache
  477.           if (!test)
  478.             back[p].r=cache_read(opt,cache,adr,fil,save);
  479.           else
  480.             back[p].r=cache_read(opt,cache,adr,fil,NULL);       // charger en tΩte uniquement du cache
  481.           if (!back[p].r.location) 
  482.             back[p].r.location=back[p].location_buffer;
  483.           else {    /* recopier */
  484.             strcpy(back[p].location_buffer,back[p].r.location);
  485.             back[p].r.location=back[p].location_buffer;
  486.           }
  487.  
  488.           /* Interdiction taille par le wizard? --> dΘtruire */
  489.           if (back[p].r.statuscode != -1) {  // pas d'erreur de lecture
  490.             if (!back_checksize(opt,&back[p],0)) {
  491.               back[p].status=0;  // FINI
  492.               back[p].r.statuscode=-1;
  493.               if (!back[p].testmode)
  494.                 strcpy(back[p].r.msg,"Cached file skipped (too big)");
  495.               else
  496.                 strcpy(back[p].r.msg,"Test: Cached file skipped  (too big)");
  497.               return 0;
  498.             }
  499.           }
  500.  
  501.           if (back[p].r.statuscode != -1) {  // pas d'erreur de lecture
  502.             if ((opt->debug>0) && (opt->log!=NULL)) {
  503.               if (!test) {
  504.                 fspc(opt->log,"debug"); fprintf(opt->log,"File immediately loaded from cache: %s%s"LF,back[p].url_adr,back[p].url_fil); test_flush;
  505.               } else {
  506.                 fspc(opt->log,"debug"); fprintf(opt->log,"File immediately tested from cache: %s%s"LF,back[p].url_adr,back[p].url_fil); test_flush;
  507.               }
  508.             }
  509.             back[p].r.notmodified=1;    // fichier non modifiΘ
  510.             back[p].status=0;  // OK prΩt
  511.  
  512.             // finalize transfer
  513.             if (!test) {
  514.               if (back[p].r.statuscode>0) {
  515.                 back_finalize(opt,cache,back,p);
  516.               }
  517.             }
  518.  
  519.             return 0;
  520.           } else {  // erreur
  521.             // effacer r
  522.             bzero((char*) &(back[p].r), sizeof(htsblk)); back[p].r.soc=INVALID_SOCKET; back[p].r.location=back[p].location_buffer;
  523.             // et continuer (chercher le fichier)
  524.           }
  525.           
  526.         } else if (cache->type==2) {    // si en cache, demander de tester If-Modified-Since
  527.           htsblk* r=cache_header(opt,cache,adr,fil);
  528.  
  529.           /* Interdiction taille par le wizard? */
  530.           {
  531.             LLint save_totalsize=back[p].r.totalsize;
  532.             back[p].r.totalsize=r->totalsize;
  533.             if (!back_checksize(opt,&back[p],1)) {
  534.               r=NULL;
  535.               //
  536.               back[p].status=0;  // FINI
  537.               deletehttp(&back[p].r); back[p].r.soc=INVALID_SOCKET;
  538.               if (!back[p].testmode)
  539.                 strcpy(back[p].r.msg,"File too big");
  540.               else
  541.                 strcpy(back[p].r.msg,"Test: File too big");
  542.               return 0;
  543.             }
  544.             back[p].r.totalsize=save_totalsize;
  545.           }
  546.           
  547.           if (r) {
  548.             if (r->statuscode==200) {     // uniquement des 200 (OK)
  549.               if (strnotempty(r->etag)) {  // ETag (RFC2616)
  550.                 if (strnotempty(r->lastmodified))
  551.                   sprintf(back[p].send_too,"If-None-Match: %s\r\nIf-Modified-Since: %s\r\n",r->etag,r->lastmodified);
  552.                 else
  553.                   sprintf(back[p].send_too,"If-None-Match: %s\r\n",r->etag);
  554.               }
  555.               else if (strnotempty(r->lastmodified))
  556.                 sprintf(back[p].send_too,"If-Modified-Since: %s\r\n",r->lastmodified);
  557.               else if (strnotempty(cache->lastmodified))
  558.                 sprintf(back[p].send_too,"If-Modified-Since: %s\r\n",cache->lastmodified);
  559.  
  560.               /* this is an update of a file */
  561.               if (strnotempty(back[p].send_too))
  562.                 back[p].is_update=1;
  563.  
  564.             }
  565.              /* else if (strnotempty(cache->lastmodified))
  566.               sprintf(back[p].send_too,"If-Modified-Since: %s\r\n",cache->lastmodified);
  567.              */
  568.           }
  569. #if DEBUGCA
  570.           printf("..is modified test %s\n",back[p].send_too);
  571. #endif
  572.         } 
  573.         // Okay, pas trouvΘ dans le cache
  574.         // Et si le fichier existe sur disque?
  575.         // Pas dans le cache: fichier n'a pas ΘtΘ transfΘrΘ du tout, donc pas sur disque?
  576.       } else {
  577.         if (fexist(save)) {    // fichier existe? aghl!
  578.           LLint sz=fsize(save);
  579.           // Bon, lα il est possible que le fichier ait ΘtΘ partiellement transfΘrΘ
  580.           // (s'il l'avait ΘtΘ en totalitΘ il aurait ΘtΘ inscrit dans le cache ET existerait sur disque)
  581.           // PAS de If-Modified-Since, on a pas connaissance des donnΘes α la date du cache
  582.           // On demande juste les donnΘes restantes si le date est valide (206), tout sinon (200)
  583.           if ((ishtml(save) != 1) && (ishtml(back[p].url_fil)!=1)) {   // NON HTML (liens changΘs!!)
  584.             if (sz>0) {    // Fichier non vide? (question bΩte, sinon on transfert tout!)
  585.               if (strnotempty(cache->lastmodified)) {     /* pas de If-.. possible */
  586.                 /*if ( (!opt->http10) && (strnotempty(cache->lastmodified)) ) { */    /* ne pas forcer 1.0 */
  587. #if DEBUGCA
  588.                 printf("..if unmodified since %s size "LLintP"\n",cache->lastmodified,(LLint)sz);
  589. #endif
  590.                 if ((opt->debug>1) && (opt->log!=NULL)) {
  591.                   fspc(opt->log,"debug"); fprintf(opt->log,"File partially present ("LLintP" bytes): %s%s"LF,(LLint)sz,back[p].url_adr,back[p].url_fil); test_flush;
  592.                 }
  593.                 
  594.                 /* impossible - don't have etag or date
  595.                 if (strnotempty(back[p].r.etag)) {  // ETag (RFC2616)
  596.                 sprintf(back[p].send_too,"If-None-Match: %s\r\n",back[p].r.etag);
  597.                 back[p].http11=1;    // En tΩte 1.1
  598.                 } else if (strnotempty(back[p].r.lastmodified)) {
  599.                 sprintf(back[p].send_too,"If-Unmodified-Since: %s\r\n",back[p].r.lastmodified);
  600.                 back[p].http11=1;    // En tΩte 1.1
  601.                 } else 
  602.                 */
  603.                 if (strlen(cache->lastmodified)) {
  604.                   sprintf(back[p].send_too,
  605.                     "If-Unmodified-Since: %s\r\nRange: bytes="LLintP"-\r\n"
  606.                     ,cache->lastmodified,(LLint)sz);
  607.                   back[p].http11=1;    // En tΩte 1.1
  608.                   back[p].range_req_size=sz;
  609.                   back[p].r.req.range_used=1;
  610.                   back[p].r.req.nocompression=1;
  611.                 } else {
  612.                   if ((opt->debug>0) && (opt->errlog!=NULL)) {
  613.                     fspc(opt->log,"warning"); fprintf(opt->log,"Could not find timestamp for partially present file, restarting (lost "LLintP" bytes): %s%s"LF,(LLint)sz,back[p].url_adr,back[p].url_fil); test_flush;
  614.                   }
  615.                 }
  616.                 
  617.               } else { 
  618.                 if ((opt->debug>0) && (opt->errlog!=NULL)) {
  619.                   fspc(opt->errlog,"warning");
  620.                   /*
  621.                   if (opt->http10)
  622.                   fprintf(opt->errlog,"File partially present (%d bytes) retransfered due to HTTP/1.0 settings: %s%s"LF,sz,back[p].url_adr,back[p].url_fil);
  623.                   else
  624.                   */
  625.                   fprintf(opt->errlog,"File partially present ("LLintP" bytes) retransfered due to lack of cache: %s%s"LF,(LLint)sz,back[p].url_adr,back[p].url_fil); 
  626.                   test_flush;
  627.                 }
  628.                 /* Sinon requΩte normale... */
  629.                 back[p].http11=0;
  630.               }
  631.             } else if (opt->norecatch) {              // tester norecatch
  632.               filenote(save,NULL);       // ne pas purger tout de mΩme
  633.               back[p].status=0;  // OK prΩt
  634.               back[p].r.statuscode=-1;  // erreur
  635.               strcpy(back[p].r.msg,"Null-size file not recaught");
  636.               return 0;
  637.             }
  638.           } else {
  639.             if ((opt->debug>0) && (opt->errlog!=NULL)) {
  640.               fspc(opt->errlog,"warning");
  641.               fprintf(opt->errlog,"HTML file ("LLintP" bytes) retransfered due to lack of cache: %s%s"LF,(LLint)sz,back[p].url_adr,back[p].url_fil); 
  642.               test_flush;
  643.             }
  644.             /* Sinon requΩte normale... */
  645.             back[p].http11=0;
  646.           }
  647.         }
  648.       }
  649.     }
  650.  
  651.  
  652.     {
  653.       ///htsblk r;   non directement dans la structure-rΘponse!
  654.       T_SOC soc;
  655.       
  656.       // ouvrir liaison, envoyer requΦte
  657.       // ne pas traiter ou recevoir l'en tΩte immΘdiatement
  658.       bzero((char*) &(back[p].r), sizeof(htsblk)); back[p].r.soc=INVALID_SOCKET; back[p].r.location=back[p].location_buffer;
  659.       // recopier proxy
  660.       bcopy((char*) &opt->proxy,(char*) &(back[p].r.req.proxy), sizeof(opt->proxy));
  661.       // et user-agent
  662.       strcpy(back[p].r.req.user_agent,opt->user_agent);
  663.       strcpy(back[p].r.req.lang_iso,opt->lang_iso);
  664.       back[p].r.req.user_agent_send=opt->user_agent_send;
  665.       // et http11
  666.       back[p].r.req.http11=back[p].http11;
  667.       back[p].r.req.nocompression=opt->nocompression;
  668.  
  669.       // mode ftp, court-circuit!
  670.       if (strfield(back[p].url_adr,"ftp://")) {
  671.         if (back[p].testmode) {
  672.           if ((opt->debug>1) && (opt->errlog!=NULL)) {
  673.             fspc(opt->errlog,"debug"); fprintf(opt->errlog,"error: forbidden test with ftp link for back_add"LF);
  674.           }
  675.           return -1;    // erreur pas de test permis
  676.         }
  677.         if (!(back[p].r.req.proxy.active && opt->ftp_proxy)) { // connexion directe, gΘrΘe en thread
  678.           back[p].status=1000;   // connexion ftp
  679. #if USE_BEGINTHREAD
  680.           launch_ftp(&(back[p]));
  681. #else
  682.           {
  683.             char nid[32];
  684.             sprintf(nid,"htsftp%d-in_progress.lock",p);
  685.             strcpy(back[p].location_buffer,fconcat(opt->path_log,nid));
  686.           }
  687.           launch_ftp(&(back[p]),back[p].location_buffer,opt->exec);
  688. #endif
  689.           return 0;
  690.         }
  691.       }
  692.       
  693. #if HTS_XGETHOST
  694. #if HDEBUG
  695.       printf("back_solve..\n");
  696. #endif
  697.       back[p].status=101;    // tentative de rΘsolution du nom de host
  698.       soc=INVALID_SOCKET;    // pas encore ouverte
  699.       back_solve(&back[p]);  // prΘparer
  700.       if (host_wait(&back[p])) {  // prΩt, par ex fichier ou dispo dans dns
  701. #if HDEBUG
  702.       printf("ok, dns cache ready..\n");
  703. #endif
  704.         soc=http_xfopen(0,0,0,back[p].send_too,adr,fil,&(back[p].r));
  705.         if (soc==INVALID_SOCKET) {
  706.           back[p].status=0;  // fini, erreur
  707.         }
  708.       }
  709. //
  710. #else
  711. //
  712. #if CNXDEBUG
  713.       printf("XFopen..\n");
  714. #endif
  715.  
  716.       if (strnotempty(back[p].send_too))    // envoyer un if-modified-since
  717. #if HTS_XCONN
  718.       soc=http_xfopen(0,0,0,back[p].send_too,adr,fil,&(back[p].r));
  719. #else
  720.       soc=http_xfopen(0,0,1,back[p].send_too,adr,fil,&(back[p].r));
  721. #endif
  722.       else
  723. #if HTS_XCONN
  724.         soc=http_xfopen(test,0,0,NULL,adr,fil,&(back[p].r));
  725. #else
  726.       soc=http_xfopen(test,0,1,NULL,adr,fil,&(back[p].r));
  727. #endif
  728. #endif
  729.       if (opt->timeout>0) {    // gestion du opt->timeout
  730.         back[p].timeout=opt->timeout;
  731.         back[p].timeout_refresh=time_local();
  732.       } else {
  733.         back[p].timeout=-1;    // pas de gestion (default)
  734.       }
  735.       
  736.       if (opt->rateout>0) {    // gestion d'un taux minimum de transfert tolΘrΘ
  737.         back[p].rateout=opt->rateout;
  738.         back[p].rateout_time=time_local();
  739.       } else {
  740.         back[p].rateout=-1;    // pas de gestion (default)
  741.       }
  742.  
  743.       // Note: on charge les code-page erreurs (erreur 404, etc) dans le cas o∙ cela est
  744.       // rattrapable (exemple: 301,302 moved xxx -> refresh sur la page!)
  745.       //if ((back[p].statuscode!=200) || (soc<0)) { // ERREUR HTTP/autre
  746.  
  747. #if CNXDEBUG
  748. printf("Xfopen ok, poll..\n");
  749. #endif
  750.  
  751. #if HTS_XGETHOST
  752.     if (soc!=INVALID_SOCKET)
  753.       if (back[p].status==101) {  // pas d'erreur
  754.         if (!back[p].r.is_file)
  755.           back[p].status=100;   // connexion en cours
  756.         else
  757.           back[p].status=1;     // fichier
  758.       }
  759.  
  760. #else
  761.       if (soc==INVALID_SOCKET) { // erreur socket
  762.         back[p].status=0;    // FINI
  763.         //if (back[p].soc!=INVALID_SOCKET) deletehttp(back[p].soc);
  764.         back[p].r.soc=INVALID_SOCKET;
  765.       } else {
  766.         if (!back[p].r.is_file)
  767. #if HTS_XCONN
  768.           back[p].status=100;   // connexion en cours
  769. #else
  770.           back[p].status=99;    // chargement en tΩte en cours
  771. #endif
  772.         else
  773.           back[p].status=1;     // chargement fichier
  774. #if BDEBUG==1
  775.         printf("..loading header\n");
  776. #endif
  777.       }
  778. #endif
  779.       
  780.     }
  781.  
  782.  
  783.     // note: si il y a erreur (404,etc) status=2 (terminΘ/Θchec) mais
  784.     // le lien est considΘrΘ comme traitΘ
  785.     //if (back[p].soc<0)  // erreur
  786.     //  return -1;
  787.  
  788.     return 0;
  789.   } else {
  790.     if ((opt->debug>1) && (opt->errlog!=NULL)) {
  791.       fspc(opt->errlog,"debug"); fprintf(opt->errlog,"error: no space left in stack for back_add"LF);
  792.     }
  793.     return -1;    // plus de place
  794.   }
  795. }
  796.  
  797.  
  798.  
  799. #if HTS_XGETHOST
  800. #if USE_BEGINTHREAD
  801. // lancement multithread du robot
  802. PTHREAD_TYPE Hostlookup(void* iadr_p) {
  803.   char iadr[256];
  804.   t_dnscache* cache=_hts_cache();  // adresse du cache
  805.   t_hostent* hp;
  806.   int error_found=0;
  807.  
  808.   // recopier (aprΦs id:pass)
  809. #if DEBUGDNS 
  810.   printf("resolv in background: %s\n",jump_identification(iadr_p));
  811. #endif
  812.   strcpy(iadr,jump_identification(iadr_p));
  813.   // couper Θventuel :
  814.   {
  815.     char *a;
  816.     if ( (a=strchr(iadr,':')) )
  817.       *a='\0';
  818.   }
  819.   freet(iadr_p);
  820.  
  821.   // attendre que le cache dns soit prΩt
  822.   while(_hts_lockdns(-1));  // attendre libΘration
  823.   _hts_lockdns(1);          // locker
  824.   while(cache->n) {
  825.     if (strcmp(cache->iadr,iadr)==0) {
  826.       error_found=1;
  827.     }
  828.     cache=cache->n;    // calculer queue
  829.   }
  830.   if (strcmp(cache->iadr,iadr)==0) {
  831.     error_found=1;
  832.   }
  833.  
  834.   if (!error_found) {
  835.     // en gros copie de hts_gethostbyname sans le return
  836.     cache->n=(t_dnscache*) calloct(1,sizeof(t_dnscache));
  837.     if (cache->n!=NULL) {
  838.       strcpy(cache->n->iadr,iadr);
  839.       cache->n->host_length=0;        /* pour le moment rien */
  840.       cache->n->n=NULL;
  841.       _hts_lockdns(0);          // dΘlocker
  842.       
  843.       /* resolve */
  844. #if DEBUGDNS 
  845.       printf("gethostbyname() in progress for %s\n",iadr);
  846. #endif
  847.       hp=gethostbyname(iadr);  // rΘsolution IP
  848.       
  849.       /* okay, result */
  850.       if (hp!=NULL) {
  851.         bcopy(hp->h_addr,cache->n->host_addr,hp->h_length);       // write first
  852.         cache->n->host_length=hp->h_length;                       // then write this
  853.       } else {
  854.         cache->n->host_addr[0]='\0';
  855.         cache->n->host_length=-1;             // dΘclarer erreur dans le dns
  856.       }
  857.     } else 
  858.     _hts_lockdns(0);          // dΘlocker
  859.   } else {
  860. #if DEBUGDNS 
  861.     printf("aborting resolv for %s (found)\n",iadr);
  862. #endif
  863.     _hts_lockdns(0);          // dΘlocker
  864.   }
  865.   // fin de copie de hts_gethostbyname
  866.  
  867. #if DEBUGDNS 
  868.   printf("quitting resolv for %s (result: %d)\n",iadr,(cache->n!=NULL)?cache->n->host_length:(-999));
  869. #endif
  870.  
  871.   return PTHREAD_RETURN;     /* _endthread implied  */
  872. }
  873. #endif
  874.  
  875. // attendre que le host (ou celui du proxy) ait ΘtΘ rΘsolu
  876. // si c'est un fichier, la rΘsolution est immΘdiate
  877. // idem pour ftp://
  878. void back_solve(lien_back* back) {
  879.   if ((!strfield(back->url_adr,"file://")) && (!strfield(back->url_adr,"ftp://"))) {
  880.   //## if (back->url_adr[0]!=lOCAL_CHAR) {  // qq chose α prΘparer
  881.     char* a;
  882.     if (!(back->r.req.proxy.active))
  883.       a=back->url_adr;
  884.     else
  885.       a=back->r.req.proxy.name;
  886.     if (!hts_dnstest(a)) {   // non encore testΘ!..
  887.       // inscire en thread
  888. #if HTS_WIN
  889.       // Windows
  890. #if USE_BEGINTHREAD
  891.       {
  892.         char* p = calloct(strlen(a)+2,1);
  893.         if (p) {
  894.           strcpy(p,a);
  895.           _beginthread( Hostlookup , 0, p );
  896.         }
  897.       }
  898. #else
  899.       /*t_hostent* h=*/
  900.       /*hts_gethostbyname(a);*/  // calcul
  901. #endif
  902. #else
  903. #if USE_BEGINTHREAD
  904.         char* p = calloct(strlen(a)+2,1);
  905.         if (p) {
  906.           strcpy(p,a);
  907.           _beginthread( Hostlookup , 0, p );
  908.         }
  909. #else
  910.       // Sous Unix, le gethostbyname() est bloquant..
  911.       /*t_hostent* h=*/
  912.       /*hts_gethostbyname(a);*/  // calcul
  913. #endif
  914. #endif
  915.     }
  916.   }
  917. }
  918.  
  919. // dΘtermine si le host a pu Ωtre rΘsolu
  920. int host_wait(lien_back* back) {
  921.   if ((!strfield(back->url_adr,"file://")) && (!strfield(back->url_adr,"ftp://"))) {
  922.   //## if (back->url_adr[0]!=lOCAL_CHAR) {
  923.     if (!(back->r.req.proxy.active)) {
  924.       return (hts_dnstest(back->url_adr));
  925.     } else {
  926.       return (hts_dnstest(back->r.req.proxy.name));      
  927.     }
  928.   } else return 1;    // prΩt, fichier local
  929. }
  930. #endif
  931.  
  932.  
  933. // Θlimine les fichiers non html en backing (anticipation)
  934. // cleanup non-html files in backing to save backing space
  935. // and allow faster "save in cache" operation
  936. void back_clean(httrackp* opt,cache_back* cache,lien_back* back,int back_max) {
  937.   int i;
  938.   for(i=0;i<back_max;i++) {
  939.     if (back[i].status == 0) {                                   // ready
  940.       if (!back[i].testmode) {                                   // not test mode
  941.         if (strnotempty(back[i].url_sav)) {                      // filename exists
  942.           if (back[i].r.is_write) {                              // not in memory (on disk, ready)
  943.             if (back[i].r.size>0) {                              // size>0
  944.               if (back[i].r.statuscode==200) {                   // HTTP "OK"
  945.                 if (!is_hypertext_mime(back[i].r.contenttype)) { // not HTML/hypertext
  946.                   if (!may_be_hypertext_mime(back[i].r.contenttype)) { // may NOT be parseable mime type
  947.                     if (back[i].pass2_ptr) {
  948.                       // finalize
  949.                       // // back_finalize(opt,cache,back,i);
  950.                       // stats
  951.                       //HTS_STAT.stat_bytes+=back[i].r.size;
  952.                       //HTS_STAT.stat_files++;
  953.                       //if ( (!back[i].r.notmodified) && (opt->is_update) ) { 
  954.                       //  HTS_STAT.stat_updated_files++;       // page modifiΘe
  955.                       //}
  956.                       //cache_mayadd(opt,cache,&back[i].r,back[i].url_adr,back[i].url_fil,back[i].url_sav);
  957.                       *back[i].pass2_ptr=-1;  // Done!
  958.                       back_delete(back,i);    // Delete backing entry
  959.                       if ((opt->debug>0) && (opt->log!=NULL)) {
  960.                         fspc(opt->log,"info"); fprintf(opt->log,"File successfully written in background: %s"LF,back[i].url_sav); test_flush;
  961.                       }
  962.                     }
  963.                   }
  964.                 }
  965.               }
  966.             }
  967.           }
  968.         }
  969.       }
  970.     }
  971.   }            
  972. }
  973.  
  974.  
  975. // attente (gestion des buffers des sockets)
  976. void back_wait(lien_back* back,int back_max,httrackp* opt,cache_back* cache,TStamp stat_timestart) {
  977.   int i;
  978.   T_SOC nfds=INVALID_SOCKET;
  979.   fd_set fds,fds_c,fds_e;     // fds pour lecture, connect (write), et erreur
  980.   int nsockets;     // nbre sockets
  981.   LLint max_read_bytes;  // max bytes read per sockets
  982.   struct timeval tv;
  983.   int do_wait=0;
  984.   int gestion_timeout=0;
  985.   int busy_recv=0;     // pas de donnΘes pour le moment   
  986.   int busy_state=0;    // pas de connexions
  987.   int max_loop;  // nombre de boucles max α parcourir..
  988. #if HTS_ANALYSTE
  989.   int max_loop_chk=0;
  990. #endif
  991.  
  992.  
  993.   // max. number of loops
  994.   max_loop=8;
  995.  
  996. #if 1
  997.   // Cleanup the stack to save space!
  998.   back_clean(opt,cache,back,back_max);
  999. #endif
  1000.  
  1001.   // recevoir tant qu'il y a des donnΘes (avec un maximum de max_loop boucles)
  1002.   do_wait=0;
  1003.   gestion_timeout=0;
  1004.   do {
  1005.     int max_c;
  1006.     busy_state=busy_recv=0;
  1007.  
  1008. #if 0
  1009.     check_rate(stat_timestart,opt->maxrate);    // vΘrifier taux de transfert
  1010. #endif
  1011.     // inscrire les sockets actuelles, et rechercher l'ID la plus ΘlevΘe
  1012.     FD_ZERO(&fds);
  1013.     FD_ZERO(&fds_c);
  1014.     FD_ZERO(&fds_e);
  1015.     nsockets=0;
  1016.     max_read_bytes=TAILLE_BUFFER;     // maximum bytes that can be read
  1017.     nfds=INVALID_SOCKET;
  1018.  
  1019.     max_c=1;
  1020.     for(i=0;i<back_max;i++) {
  1021.  
  1022.       // en cas de gestion du connect prΘemptif
  1023. #if HTS_XCONN
  1024.       if (back[i].status==100) {      // connexion
  1025.         do_wait=1;
  1026.  
  1027.         // noter socket write
  1028.         FD_SET(back[i].r.soc,&fds_c);
  1029.         
  1030.         // noter socket erreur
  1031.         FD_SET(back[i].r.soc,&fds_e);
  1032.  
  1033.         // calculer max
  1034.         if (max_c) {
  1035.           max_c=0;
  1036.           nfds=back[i].r.soc;
  1037.         } else if (back[i].r.soc>nfds) {
  1038.           // ID socket la plus ΘlevΘe
  1039.           nfds=back[i].r.soc;
  1040.         }
  1041.         
  1042.       } else
  1043. #endif
  1044. #if HTS_XGETHOST
  1045.       if (back[i].status==101) {      // attente
  1046.         // rien α faire..
  1047.       } else
  1048. #endif
  1049.       // poll pour la lecture sur les sockets
  1050.       if ((back[i].status>0) && (back[i].status<100)) {  // en rΘception http
  1051.             
  1052. #if BDEBUG==1
  1053.         //printf("....socket in progress: %d\n",back[i].r.soc);
  1054. #endif
  1055.         // non local et non ftp
  1056.         if (!back[i].r.is_file) {
  1057.         //## if (back[i].url_adr[0]!=lOCAL_CHAR) {
  1058.           
  1059.           // vΘrification de sΘcuritΘ
  1060.           if (back[i].r.soc!=INVALID_SOCKET) {  // hey, you never know..
  1061.             do_wait=1;
  1062.             
  1063.             // noter socket read
  1064.             FD_SET(back[i].r.soc,&fds);
  1065.             
  1066.             // noter socket error
  1067.             FD_SET(back[i].r.soc,&fds_e);
  1068.             
  1069.             // incrΘmenter nombre de sockets
  1070.             nsockets++;
  1071.  
  1072.             // calculer max
  1073.             if (max_c) {
  1074.               max_c=0;
  1075.               nfds=back[i].r.soc;
  1076.             } else if (back[i].r.soc>nfds) {
  1077.               // ID socket la plus ΘlevΘe
  1078.               nfds=back[i].r.soc;
  1079.             }
  1080.           } else {
  1081.             back[i].r.statuscode=-4;
  1082.             if (back[i].status==100)
  1083.               strcpy(back[i].r.msg,"Connect Error");
  1084.             else
  1085.               strcpy(back[i].r.msg,"Receive Error");
  1086.             back[i].status=0;  // terminΘ
  1087.             if ((opt->debug>0) && (opt->log!=NULL)) {
  1088.               fspc(opt->log,"warning"); fprintf(opt->log,"Unexpected socket error during pre-loop"); test_flush;
  1089.             }            
  1090.           }
  1091. #if WIDE_DEBUG
  1092.           else {
  1093.             DEBUG_W("PANIC!!! Socket is invalid in a poll test!\n");
  1094.           }
  1095. #endif
  1096.           
  1097.         }
  1098.         
  1099.       }
  1100.     }    
  1101.     nfds++;
  1102.     
  1103.     if (do_wait) {  // attendre
  1104.       // temps d'attente max: 2.5 seconde
  1105.       tv.tv_sec=HTS_SOCK_SEC;
  1106.       tv.tv_usec=HTS_SOCK_MS;
  1107.       
  1108. #if BDEBUG==1
  1109.       printf("..select\n");
  1110. #endif
  1111.       
  1112.       // poller les sockets-attention au noyau sous Unix..
  1113. #if HTS_WIDE_DEBUG    
  1114.       DEBUG_W("select\n");
  1115. #endif
  1116.       select(nfds,&fds,&fds_c,&fds_e,&tv);
  1117. #if HTS_WIDE_DEBUG    
  1118.       DEBUG_W("select done\n");
  1119. #endif      
  1120.     }
  1121.     
  1122.     // maximum data which can be received for a socket, if limited
  1123.     if (nsockets) {
  1124.       if (opt->maxrate>0) {
  1125.         max_read_bytes = ( check_downloadable_bytes(opt->maxrate) / nsockets );
  1126.       }
  1127.     }
  1128.     if (!max_read_bytes)
  1129.       busy_recv=0;
  1130.     
  1131.     // recevoir les donnΘes arrivΘes
  1132.     for(i=0;i<back_max;i++) {
  1133.       
  1134.       if (back[i].status>0) {
  1135.         if (!back[i].r.is_file) {  // not file..
  1136.           if (back[i].r.soc!=INVALID_SOCKET) {  // hey, you never know..
  1137.             int err=FD_ISSET(back[i].r.soc,&fds_e);
  1138.             if (err) {
  1139.               if (back[i].r.soc!=INVALID_SOCKET) {
  1140. #if HTS_DEBUG_CLOSESOCK
  1141.                 DEBUG_W("back_wait: deletehttp\n");
  1142. #endif
  1143.                 deletehttp(&back[i].r);
  1144.               }
  1145.               back[i].r.soc=INVALID_SOCKET;
  1146.               back[i].r.statuscode=-4;
  1147.               if (back[i].status==100)
  1148.                 strcpy(back[i].r.msg,"Connect Error");
  1149.               else
  1150.                 strcpy(back[i].r.msg,"Receive Error");
  1151.               back[i].status=0;  // terminΘ
  1152.             }
  1153.           }
  1154.         }
  1155.       }
  1156.       
  1157.       // ---- FLAG WRITE MIS A UN?: POUR LE CONNECT
  1158.       if (back[i].status==100) {   // attendre connect
  1159.         int dispo=0;
  1160.         // vΘrifier l'existance de timeout-check
  1161.         if (!gestion_timeout)
  1162.           if (back[i].timeout>0)
  1163.             gestion_timeout=1;
  1164.           
  1165.         // connectΘ?
  1166.         dispo=FD_ISSET(back[i].r.soc,&fds_c);
  1167.         if (dispo) {    // ok
  1168.           busy_state=1;
  1169. #if BDEBUG==1
  1170.           printf("..connect ok on socket %d\n",back[i].r.soc);
  1171. #endif
  1172.           /* limit nb. connections/seconds to avoid server overload */
  1173.           if (opt->maxconn>0) {
  1174.             Sleep(1000/opt->maxconn);
  1175.           }
  1176.  
  1177.           if (back[i].timeout>0) {    // refresh timeout si besoin est
  1178.             back[i].timeout_refresh=time_local();
  1179.           }
  1180.           if (back[i].rateout>0) {    // le taux de transfert de base sur le dΘbut de la connexion
  1181.             back[i].rateout_time=time_local();
  1182.           }
  1183.           // envoyer header
  1184.           //if (strcmp(back[i].url_sav,BACK_ADD_TEST)!=0)    // vrai get
  1185.           if (!back[i].head_request)
  1186.             http_sendhead(opt->cookie,0,back[i].send_too,back[i].url_adr,back[i].url_fil,back[i].referer_adr,back[i].referer_fil,&back[i].r);         
  1187.           else if (back[i].head_request==2)  // test en GET!
  1188.             http_sendhead(opt->cookie,0,back[i].send_too,back[i].url_adr,back[i].url_fil,back[i].referer_adr,back[i].referer_fil,&back[i].r);         
  1189.           else        // test!
  1190.             http_sendhead(opt->cookie,1,back[i].send_too,back[i].url_adr,back[i].url_fil,back[i].referer_adr,back[i].referer_fil,&back[i].r);         
  1191.           back[i].status=99;  // attendre en tΩte maintenant
  1192.         }
  1193.  
  1194.         // attente gethostbyname
  1195.       } 
  1196. #if HTS_XGETHOST
  1197.       else if (back[i].status==101) {  // attendre gethostbyname
  1198. #if DEBUGDNS 
  1199.         //printf("status 101 for %s\n",back[i].url_adr);
  1200. #endif
  1201.  
  1202.         if (!gestion_timeout)
  1203.           if (back[i].timeout>0)
  1204.             gestion_timeout=1;
  1205.  
  1206.         if (host_wait(&back[i])) {    // prΩt
  1207.           back[i].status=100;        // attente connexion
  1208.           if (back[i].timeout>0) {    // refresh timeout si besoin est
  1209.             back[i].timeout_refresh=time_local();
  1210.           }
  1211.           if (back[i].rateout>0) {    // le taux de transfert de base sur le dΘbut de la connexion
  1212.             back[i].rateout_time=time_local();
  1213.           }
  1214.  
  1215.           back[i].r.soc=http_xfopen(0,0,0,back[i].send_too,back[i].url_adr,back[i].url_fil,&(back[i].r));
  1216.           if (back[i].r.soc==INVALID_SOCKET) {
  1217.             back[i].status=0;  // fini, erreur
  1218.             if (back[i].r.soc!=INVALID_SOCKET) {
  1219. #if HTS_DEBUG_CLOSESOCK
  1220.               DEBUG_W("back_wait(2): deletehttp\n");
  1221. #endif
  1222.               deletehttp(&back[i].r);
  1223.             }
  1224.             back[i].r.soc=INVALID_SOCKET;
  1225.             back[i].r.statuscode=-5;
  1226.             if (strnotempty(back[i].r.msg)==0) 
  1227.               strcpy(back[i].r.msg,"Unable to resolve host name");
  1228.           }
  1229.         }
  1230.         
  1231.  
  1232.       // ---- FLAG READ MIS A UN?: POUR LA RECEPTION
  1233.       }
  1234. #endif
  1235. #if USE_BEGINTHREAD
  1236.       // ..rien α faire, c'est magic les threads
  1237. #else
  1238.       else if (back[i].status==1000) {  // en rΘception ftp
  1239.         if (!fexist(back[i].location_buffer)) {    // terminΘ
  1240.           FILE* fp;
  1241.           fp=fopen(fconcat(back[i].location_buffer,".ok"),"rb");
  1242.           if (fp) {
  1243.             int j=0;
  1244.             fscanf(fp,"%d ",&(back[i].r.statuscode));
  1245.             while(!feof(fp)) {
  1246.               int c = fgetc(fp);
  1247.               if (c!=EOF)
  1248.                 back[i].r.msg[j++]=c;
  1249.             }
  1250.             back[i].r.msg[j++]='\0';
  1251.             fclose(fp);
  1252.             remove(fconcat(back[i].location_buffer,".ok"));
  1253.             strcpy(fconcat(back[i].location_buffer,".ok"),"");
  1254.           } else {
  1255.             strcpy(back[i].r.msg,"Unknown ftp result, check if file is ok");
  1256.             back[i].r.statuscode=-1;
  1257.           }
  1258.           back[i].status=0;
  1259.           // finalize transfer
  1260.           if (back[i].r.statuscode>0) {
  1261.             back_finalize(opt,cache,back,i);
  1262.           }
  1263.         }
  1264.       }
  1265. #endif
  1266.       else if ((back[i].status>0) && (back[i].status<1000)) {  // en rΘception http
  1267.         int dispo=0;
  1268.         
  1269.         // vΘrifier l'existance de timeout-check
  1270.         if (!gestion_timeout)
  1271.           if (back[i].timeout>0)
  1272.             gestion_timeout=1;
  1273.           
  1274.           // donnΘes dispo?
  1275.           //## if (back[i].url_adr[0]!=lOCAL_CHAR)
  1276.           if (!back[i].r.is_file) {
  1277.             dispo=FD_ISSET(back[i].r.soc,&fds);
  1278.           }
  1279.           else
  1280.             dispo=1;
  1281.  
  1282.           // Check transfer rate!
  1283.           if (!max_read_bytes)
  1284.             dispo=0;                // limit transfer rate
  1285.           
  1286.           if (dispo) {    // donnΘes dispo
  1287.             LLint retour_fread;
  1288.             busy_recv=1;    // on rΘcupΦre encore
  1289. #if BDEBUG==1
  1290.             printf("..data available on socket %d\n",back[i].r.soc);
  1291. #endif
  1292.  
  1293.             
  1294.             // range size hack old location
  1295.  
  1296. #if HTS_DIRECTDISK
  1297.             // Court-circuit:
  1298.             // Peut-on stocker le fichier directement sur disque?
  1299.             // Ahh que ca serait vachement mieux et que ahh que la mΘmoire vous dit merci!
  1300.             if (back[i].status) {
  1301.               if (back[i].r.is_write==0) {  // mode mΘmoire
  1302.                 if (back[i].r.adr==NULL) {  // rien n'a ΘtΘ Θcrit
  1303.                   if (!back[i].testmode) {  // pas mode test
  1304.                     if (strnotempty(back[i].url_sav)) {
  1305.                       if (strcmp(back[i].url_fil,"/robots.txt")) {
  1306.                         if (back[i].r.statuscode==200) {  // 'OK'
  1307.                           if (!is_hypertext_mime(back[i].r.contenttype)) {    // pas HTML
  1308.                             if (opt->getmode&2) {    // on peut ecrire des non html
  1309.                               back[i].r.is_write=1;    // Θcrire
  1310.                               if (back[i].r.compressed) {
  1311.                                 back[i].tmpfile[0]='\0';
  1312.                                 strcpy(back[i].tmpfile,tempnam(NULL,"httrZ"));
  1313.                                 if (back[i].tmpfile[0])
  1314.                                   back[i].r.out=fopen(back[i].tmpfile,"wb");
  1315.                               } else
  1316.                                 back[i].r.out=filecreate(back[i].url_sav);
  1317. #if HDEBUG
  1318.                               printf("direct-disk: %s\n",back[i].url_sav);
  1319. #endif
  1320.                               if ((opt->debug>1) && (opt->log!=NULL)) {
  1321.                                 fspc(opt->log,"debug"); fprintf(opt->log,"File received from net to disk: %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  1322.                               }
  1323.                               
  1324.                               if (back[i].r.out==NULL) {
  1325.                                 if (opt->errlog) {
  1326.                                   fspc(opt->errlog,"error");
  1327.                                   fprintf(opt->errlog,"Unable to save file %s"LF,back[i].url_sav);
  1328.                                   test_flush;
  1329.                                 }
  1330.                                 back[i].r.is_write=0;    // erreur, abandonner
  1331. #if HDEBUG
  1332.                                 printf("..error!\n");
  1333. #endif
  1334.                               }
  1335. #if HTS_WIN==0
  1336.                               else chmod(back[i].url_sav,HTS_ACCESS_FILE);      
  1337. #endif          
  1338.                             } else {  // on coupe tout!
  1339.                               if ((opt->debug>1) && (opt->log!=NULL)) {
  1340.                                 fspc(opt->log,"debug"); fprintf(opt->log,"File cancelled (non HTML): %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  1341.                               }
  1342.                               back[i].status=0;  // terminΘ
  1343.                               if (!back[i].testmode)
  1344.                                 back[i].r.statuscode=-10;    // EUHH CANCEL
  1345.                               else
  1346.                                 back[i].r.statuscode=-10;    // "TEST OK"
  1347.                               if (back[i].r.soc!=INVALID_SOCKET) {
  1348. #if HTS_DEBUG_CLOSESOCK
  1349.                                 DEBUG_W("back_wait(3): deletehttp\n");
  1350. #endif
  1351.                                 deletehttp(&back[i].r);
  1352.                               }
  1353.                               back[i].r.soc=INVALID_SOCKET;
  1354.                             }
  1355.                           }
  1356.                         }
  1357.                       }
  1358.                     }
  1359.                   }
  1360.                 }
  1361.               }
  1362.             }
  1363. #endif              
  1364.  
  1365.             // rΘception de donnΘes depuis socket ou fichier
  1366.             if (back[i].status) {
  1367.               if (back[i].status==99)  // recevoir par bloc de lignes
  1368.                 retour_fread=http_xfread1(&(back[i].r),0);
  1369.               else if (back[i].status==98) { // recevoir longueur chunk en hexa caractΦre par caractΦre
  1370.                 // backuper pour lire dans le buffer chunk
  1371.                 htsblk r;
  1372.                 bcopy((char*) &(back[i].r), (char*) &r, sizeof(htsblk));
  1373.                 back[i].r.is_write=0;                   // mΘmoire
  1374.                 back[i].r.adr=back[i].chunk_adr;        // adresse
  1375.                 back[i].r.size=back[i].chunk_size;      // taille taille chunk
  1376.                 back[i].r.totalsize=-1;                 // total inconnu
  1377.                 back[i].r.out=NULL;
  1378.                 back[i].r.is_file=0;
  1379.                 //
  1380.                 // ligne par ligne
  1381.                 retour_fread=http_xfread1(&(back[i].r),-1);
  1382.                 // modifier et restaurer
  1383.                 back[i].chunk_adr=back[i].r.adr;        // adresse
  1384.                 back[i].chunk_size=back[i].r.size;      // taille taille chunk
  1385.                 bcopy((char*) &r, (char*) &(back[i].r), sizeof(htsblk));    // restaurer vΘritable r
  1386.               }
  1387.               else if (back[i].is_chunk) {         // attention chunk, limiter taille α lire
  1388. #if CHUNKDEBUG==1
  1389.                 printf("read %d bytes\n",(int)min(back[i].r.totalsize-back[i].r.size,max_read_bytes));
  1390. #endif
  1391.                 retour_fread=(int) http_xfread1(&(back[i].r),(int) min(back[i].r.totalsize-back[i].r.size,max_read_bytes));
  1392.               } else              
  1393.                 retour_fread=(int) http_xfread1(&(back[i].r),(int) max_read_bytes);
  1394.                 // retour_fread=http_fread1(&(back[i].r));
  1395.             } else
  1396.               retour_fread=-1;                    // interruption ou annulation interne (peut ne pas Ωtre une erreur)
  1397.             
  1398.             // Si rΘception chunk, tester si on est pas α la fin!
  1399.             if (back[i].status==1) {
  1400.               if (back[i].is_chunk) {     // attendre prochain chunk
  1401.                 if (back[i].r.size==back[i].r.totalsize) {      // fin chunk!
  1402.                   //printf("chunk end at %d\n",back[i].r.size);
  1403.                   back[i].status=98;  // prochain chunk
  1404.                   if (back[i].chunk_adr!=NULL) { freet(back[i].chunk_adr); back[i].chunk_adr=NULL; } back[i].chunk_size=0;
  1405.                   retour_fread=0;       // pas d'erreur
  1406. #if CHUNKDEBUG==1
  1407.                   printf("waiting for next chunk header (soc %d)..\n",back[i].r.soc);
  1408. #endif
  1409.                 }
  1410.               }
  1411.             }
  1412.                           
  1413.             if (retour_fread==-1) {    // erreur rΘception
  1414.               back[i].status=0;    // terminΘ
  1415.               if (back[i].r.soc!=INVALID_SOCKET) {
  1416. #if HTS_DEBUG_CLOSESOCK
  1417.                 DEBUG_W("back_wait(4): deletehttp\n");
  1418. #endif
  1419.                 deletehttp(&back[i].r);
  1420.               }
  1421.               back[i].r.soc=INVALID_SOCKET;
  1422. #if CHUNKDEBUG==1
  1423.               if (back[i].is_chunk)
  1424.                 printf("must be the last chunk for %s (connection closed) - %d/%d\n",back[i].url_fil,back[i].r.size,back[i].r.totalsize);
  1425. #endif
  1426.               //if ((back[i].r.statuscode==-1) && (strnotempty(back[i].r.msg)==0)) {
  1427.               if ((back[i].r.statuscode<0) && (strnotempty(back[i].r.msg)==0)) {
  1428. #if HDEBUG
  1429.                 printf("error interruped: %s\n",back[i].r.adr);
  1430. #endif        
  1431.                 if (back[i].r.size>0)
  1432.                   strcat(back[i].r.msg,"Interrupted transfer");
  1433.                 else
  1434.                   strcat(back[i].r.msg,"No data (connection closed)");
  1435.                 back[i].r.statuscode=-4;
  1436.               }
  1437.  
  1438.               // finalize transfer
  1439.               if (back[i].r.statuscode>0) {
  1440.                 back_finalize(opt,cache,back,i);
  1441.               }
  1442.  
  1443.               if (back[i].r.totalsize>0) {    // tester totalsize
  1444.               //if ((back[i].r.totalsize>0) && (back[i].status==99)) {    // tester totalsize
  1445.                 if (back[i].r.totalsize!=back[i].r.size) {  // pas la mΩme!
  1446.                   if (!opt->tolerant) {
  1447.                     //#if HTS_CL_IS_FATAL
  1448.                     if (back[i].r.adr) freet(back[i].r.adr); back[i].r.adr=NULL;
  1449.                     if (back[i].r.size<back[i].r.totalsize)
  1450.                       back[i].r.statuscode=-4;        // recatch
  1451.                     sprintf(back[i].r.msg,"Incorrect length ("LLintP" Bytes, "LLintP" expected)",back[i].r.size,back[i].r.totalsize);
  1452.                   } else {
  1453.                     //#else
  1454.                     // Un warning suffira..
  1455.                     if (cache->errlog!=NULL) {
  1456.                       fspc(cache->errlog,"warning"); fprintf(cache->errlog,"Incorrect length ("LLintP"!="LLintP" expected) for %s%s"LF,back[i].r.size,back[i].r.totalsize,back[i].url_adr,back[i].url_fil);
  1457.                     }
  1458.                     //#endif
  1459.                   }
  1460.                 }
  1461.               }
  1462. #if BDEBUG==1
  1463.               printf("transfer ok\n");
  1464. #endif
  1465.             } else {    // pas d'erreur de rΘception
  1466.               if (back[i].timeout>0) {    // refresh timeout si besoin est
  1467.                 back[i].timeout_refresh=time_local();
  1468.               }
  1469.  
  1470.               // Traitement des en tΩtes chunks ou en tΩtes
  1471.               if (back[i].status==98) {        // rΘception taille chunk en hexa (  aprΦs les en tΩtes, peut ne pas
  1472.                 if (back[i].chunk_size>=2) {
  1473.                   int chunk_size=-1;
  1474.                   // Ωtre prΘsent)
  1475.                   if (back[i].chunk_adr[back[i].chunk_size-1]==10) {    // LF, fin ligne chunk
  1476.                     char chunk_data[64];
  1477.                     if (back[i].chunk_size<32) {      // pas trop gros
  1478.                       back[i].chunk_adr[ back[i].chunk_size-1]='\0';    // octet nul 
  1479.                       strcpy(chunk_data,"");    // hex number
  1480.                       strcat(chunk_data,back[i].chunk_adr);
  1481. #if CHUNKDEBUG==1
  1482.                       printf("chunk received and read: %s\n",chunk_data);
  1483. #endif
  1484.                       if (back[i].r.totalsize<0)
  1485.                         back[i].r.totalsize=0;        // initialiser α 0
  1486.                       if (sscanf(chunk_data,"%x",&chunk_size) == 1) {
  1487.                         back[i].r.totalsize+=chunk_size;    // noter taille
  1488.                         back[i].r.adr=(char*) realloct(back[i].r.adr,(INTsys) back[i].r.totalsize + 1);
  1489.                         if (!back[i].r.adr) {
  1490.                           if (cache->errlog!=NULL) {
  1491.                             fprintf(cache->errlog,"Error: Not enough memory ("LLintP") for %s%s"LF,back[i].r.totalsize,back[i].url_adr,back[i].url_fil);
  1492.                           }
  1493.                         }
  1494. #if CHUNKDEBUG==1
  1495.                         printf("chunk length: %d - next total "LLintP":\n",chunk_size,back[i].r.totalsize);
  1496. #endif
  1497.                       } else                                
  1498.                         if (cache->errlog!=NULL) {
  1499.                           fprintf(cache->errlog,"Warning: Illegal chunk (%s) for %s%s"LF,back[i].chunk_adr,back[i].url_adr,back[i].url_fil);
  1500.                         }
  1501.                     } else {                                  
  1502.                       if (cache->errlog!=NULL) {
  1503.                         fprintf(cache->errlog,"Warning: Chunk too big ("LLintP") for %s%s"LF,back[i].chunk_size,back[i].url_adr,back[i].url_fil);
  1504.                       }
  1505.                     }
  1506.                     
  1507.                     // ok, continuer sur le body
  1508.                     
  1509.                     // si chunk non nul continuer (ou commencer)
  1510.                     if (chunk_size>0) {
  1511.                       back[i].status=1;     // continuer body    
  1512. #if CHUNKDEBUG==1
  1513.                       printf("waiting for body (chunk)\n");
  1514. #endif
  1515.                     } else {                // chunk nul, c'est la fin
  1516. #if CHUNKDEBUG==1
  1517.                       printf("chunk end, total: %d\n",back[i].r.size);
  1518. #endif
  1519.                       back[i].status=0;     // fin  
  1520.                       // finalize transfer
  1521.                       back_finalize(opt,cache,back,i);
  1522.                       if (back[i].r.soc!=INVALID_SOCKET) {
  1523. #if HTS_DEBUG_CLOSESOCK
  1524.                         DEBUG_W("back_wait(5): deletehttp\n");
  1525. #endif
  1526.                         deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1527.  
  1528.                         /* Tester totalsize en fin de chunk */
  1529.                         if ((back[i].r.totalsize>0)) {    // tester totalsize
  1530.                           if (back[i].r.totalsize!=back[i].r.size) {  // pas la mΩme!
  1531. #if HTS_CL_IS_FATAL
  1532.                             if (back[i].r.adr) { freet(back[i].r.adr); back[i].r.adr=NULL; }
  1533.                             back[i].r.statuscode=-1;
  1534.                             strcpy(back[i].r.msg,"Incorrect length");
  1535. #else
  1536.                             // Un warning suffira..
  1537.                             if (cache->errlog!=NULL) {
  1538.                               fspc(cache->errlog,"warning"); fprintf(cache->errlog,"Incorrect length ("LLintP"!="LLintP" expected) for %s%s"LF,back[i].r.size,back[i].r.totalsize,back[i].url_adr,back[i].url_fil);
  1539.                             }
  1540. #endif
  1541.                           }
  1542.                         }
  1543.                         
  1544.                       
  1545.                       }
  1546.                     }
  1547.  
  1548.                     // effacer buffer (chunk en tete)
  1549.                     if (back[i].chunk_adr!=NULL) {
  1550.                       freet(back[i].chunk_adr);
  1551.                       back[i].chunk_adr=NULL;
  1552.                       back[i].chunk_size=0;
  1553.                     }
  1554.                   
  1555.                   } // chunk LF?
  1556.                 }  // taille buffer chunk>2
  1557.                 //
  1558.               } else if (back[i].status==99) {        // en tΩtes (avant le chunk si il est prΘsent)
  1559.                 //
  1560.                 if (back[i].r.size>=2) {
  1561.                   // double LF
  1562.                   if ((back[i].r.adr[back[i].r.size-1]==10) && (back[i].r.adr[back[i].r.size-2]==10)) {
  1563.                     char rcvd[2048];
  1564.                     int ptr=0;
  1565.                     
  1566. #if BDEBUG==1
  1567.                     printf("..ok, header received\n");
  1568. #endif
  1569.  
  1570.                     // ----------------------------------------
  1571.                     // traiter en-tΩte!
  1572.                     // status-line α rΘcupΘrer
  1573.                     ptr+=binput(back[i].r.adr+ptr,rcvd,2000);
  1574.                     if (strnotempty(rcvd)==0)
  1575.                       ptr+=binput(back[i].r.adr+ptr,rcvd,2000);    // "certains serveurs buggΘs envoient un \n au dΘbut" (RFC)
  1576.                     
  1577.                     // traiter status-line
  1578.                     treatfirstline(&back[i].r,rcvd);
  1579.                     
  1580. #if HDEBUG
  1581.                     printf("(Buffer) Status-Code=%d\n",back[i].r.statuscode);
  1582. #endif
  1583.                     if (_DEBUG_HEAD) {
  1584.                       if (ioinfo) {
  1585.                         fprintf(ioinfo,"response for %s%s:\r\ncode=%d\r\n",jump_identification(back[i].url_adr),back[i].url_fil,back[i].r.statuscode);
  1586.                         fprintfio(ioinfo,back[i].r.adr,">>> ");
  1587.                         fprintf(ioinfo,"\r\n");
  1588.                         fflush(ioinfo);
  1589.                       }                    // en-tΩte
  1590.                     }
  1591.                       
  1592.                     // header // ** !attention! HTTP/0.9 non supportΘ
  1593.                     do {
  1594.                       ptr+=binput(back[i].r.adr+ptr,rcvd,2000);          
  1595. #if HDEBUG
  1596.                       printf("(buffer)>%s\n",rcvd);      
  1597. #endif
  1598.                       /*
  1599.                       if (_DEBUG_HEAD) {
  1600.                         if (ioinfo) {
  1601.                           fprintf(ioinfo,"(buffer)>%s\r\n",rcvd);      
  1602.                           fflush(ioinfo);
  1603.                         }
  1604.                       }
  1605.                       */
  1606.  
  1607.                       if (strnotempty(rcvd))
  1608.                         treathead(opt->cookie,back[i].url_adr,back[i].url_fil,&back[i].r,rcvd);  // traiter
  1609.                       
  1610.                       // parfois les serveurs buggΘs renvoient un content-range avec un 200
  1611.                       if (back[i].r.statuscode==200)  // 'OK'
  1612.                         if (strfield(rcvd,"content-range:"))  // Avec un content-range: relisez les RFC..
  1613.                           back[i].r.statuscode=206;    // FORCER A 206 !!!!!
  1614.                         
  1615.                     } while(strnotempty(rcvd));
  1616.                     // ----------------------------------------                    
  1617.                     
  1618.                     // libΘrer mΘmoire  -- aprΦs! --
  1619.                     if (back[i].r.adr!=NULL) { freet(back[i].r.adr); back[i].r.adr=NULL; }
  1620.  
  1621.                     
  1622.  
  1623.  
  1624.                     /* 
  1625.                        Status code and header-response hacks
  1626.                     */
  1627.                     
  1628.                     // Check response : 203 == 200
  1629.                     if (back[i].r.statuscode==203) {  // 'Non-Authoritative Information'
  1630.                       back[i].r.statuscode=200;       // forcer "OK"
  1631.                     } else if (back[i].r.statuscode == 100) {
  1632.                       back[i].status=99;
  1633.                       back[i].r.size=0;
  1634.                       back[i].r.totalsize=0;
  1635.                       back[i].chunk_size=0;
  1636.                       back[i].r.statuscode=-1;
  1637.                       back[i].r.msg[0]='\0';
  1638.                       /*
  1639.                       { // xxc xxc
  1640.                         char mybuff[256]="\0";
  1641.                         int retour=recv(back[i].r.soc,mybuff,32,0);
  1642.                       }
  1643.                       */
  1644.                       if ((opt->debug>1) && (opt->log!=NULL)) {
  1645.                         fspc(opt->log,"debug"); fprintf(opt->log,"Status 100 detected for %s%s, continuing headers"LF,back[i].url_adr,back[i].url_fil); test_flush;
  1646.                       }
  1647.                       continue;
  1648.                     }
  1649.                     
  1650.  
  1651.                     // Various hacks to limit re-transfers when updating a mirror
  1652.                     if (opt->sizehack) {
  1653.                       // We already have the file
  1654.                       // and ask the remote server for an update
  1655.                       // Some servers, especially dynamic pages severs, always
  1656.                       // answer that the page has been modified since last visit
  1657.                       // And answer with a 200 (OK) response, and the same page
  1658.                       // If the size is the same, and the option has been set, we assume
  1659.                       // that the file is identical - and therefore let's break the connection
  1660.                       if (back[i].is_update) {          // mise α jour
  1661.                         if (back[i].r.statuscode==200) {  // 'OK'
  1662.                           htsblk r = cache_read(opt,cache,back[i].url_adr,back[i].url_fil,NULL);    // lire entrΘe cache
  1663.                           if (r.statuscode == 200) {  // OK pas d'erreur cache
  1664.                             LLint len1,len2;
  1665.                             len1=r.totalsize;
  1666.                             len2=back[i].r.totalsize;
  1667.                             if (r.size>0)
  1668.                               len1=r.size;
  1669.                             if (len1>0) {
  1670.                               if (len1 == len2) {             // tailles identiques
  1671.                                 back[i].r.statuscode=304;     // forcer NOT MODIFIED
  1672.                                 deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1673.                                 if ((opt->debug>1) && (opt->log!=NULL)) {
  1674.                                   fspc(opt->log,"debug"); fprintf(opt->log,"File seems complete (same size), breaking connection: %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  1675.                                 }
  1676.                               }
  1677.                             }
  1678.                           } else {
  1679.                             if (opt->errlog!=NULL) {
  1680.                               fspc(opt->errlog,"warning"); fprintf(opt->errlog,"File seems complete (same size), but there was a cache read error: %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  1681.                             }
  1682.                           }
  1683.                         }
  1684.                       }
  1685.                     }
  1686.  
  1687.                     // Various hacks to limit re-transfers when updating a mirror
  1688.                     if (opt->sizehack) {
  1689.                       // We have request for a partial file (with a 'Range: NNN-' header)
  1690.                       // and received a complete file notification (200), with 'Content-length: NNN'
  1691.                       // it might be possible that we had the complete file
  1692.                       // this is the case in *most* cases, so break the connection
  1693.                       if (back[i].r.is_write==0) {  // mode mΘmoire
  1694.                         if (back[i].r.adr==NULL) {  // rien n'a ΘtΘ Θcrit
  1695.                           if (!back[i].testmode) {  // pas mode test
  1696.                             if (strnotempty(back[i].url_sav)) {
  1697.                               if (strcmp(back[i].url_fil,"/robots.txt")) {
  1698.                                 if (back[i].r.statuscode==200) {  // 'OK'
  1699.                                   if (!is_hypertext_mime(back[i].r.contenttype)) {    // pas HTML
  1700.                                     if (back[i].r.statuscode==200) {      // "OK"
  1701.                                       if (back[i].range_req_size>0) {     // but Range: requested
  1702.                                         if (back[i].range_req_size == back[i].r.totalsize) {    // And same size
  1703. #if HTS_DEBUG_CLOSESOCK
  1704.                                           DEBUG_W("back_wait(skip_range): deletehttp\n");
  1705. #endif
  1706.                                           deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1707.                                           back[i].status=0;    // READY
  1708.                                           back[i].r.size=back[i].r.totalsize;
  1709.                                           filenote(back[i].url_sav,NULL);
  1710.                                           back[i].r.statuscode=304;     // NOT MODIFIED
  1711.                                           if ((opt->debug>1) && (opt->log!=NULL)) {
  1712.                                             fspc(opt->log,"debug"); fprintf(opt->log,"File seems complete (reget failed), breaking connection: %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  1713.                                           }
  1714.                                         }
  1715.                                       }
  1716.                                     }
  1717.                                     
  1718.                                   }
  1719.                                 }
  1720.                               }
  1721.                             }
  1722.                           }
  1723.                         }
  1724.                       }
  1725.                     }
  1726.                     // END - Various hacks to limit re-transfers when updating a mirror
  1727.  
  1728.                     /* 
  1729.                     End of status code and header-response hacks
  1730.                     */
  1731.  
  1732.                     
  1733.                     
  1734.                     /* Interdiction taille par le wizard? */
  1735.                     if (back[i].r.soc!=INVALID_SOCKET) {
  1736.                       if (!back_checksize(opt,&back[i],1)) {
  1737.                         back[i].status=0;  // FINI
  1738.                         deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1739.                         if (!back[i].testmode)
  1740.                           strcpy(back[i].r.msg,"File too big");
  1741.                         else
  1742.                           strcpy(back[i].r.msg,"Test: File too big");
  1743.                       }
  1744.                     }
  1745.                     
  1746.                     /* sinon, continuer */
  1747.                     /* if (back[i].r.soc!=INVALID_SOCKET) {   // ok rΘcupΘrer body? */
  1748.                     // head: terminΘ
  1749.                     if (back[i].head_request) {
  1750.                       if ((opt->debug>1) && (opt->log!=NULL)) {
  1751.                         fspc(opt->log,"debug"); fprintf(opt->log,"Tested file: %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  1752.                       }
  1753. #if HTS_DEBUG_CLOSESOCK
  1754.                       DEBUG_W("back_wait(head request): deletehttp\n");
  1755. #endif
  1756.                       // Couper connexion
  1757.                       deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1758.                       back[i].status=0;  // terminΘ
  1759.                     }
  1760.                     // traiter une Θventuelle erreur 304 (cache α jour utilisable)
  1761.                     else if (back[i].r.statuscode==304) {  // document α jour dans le cache
  1762.                       // lire dans le cache
  1763.                       // ** NOTE: pas de vΘrif de la taille ici!!
  1764. #if HTS_DEBUG_CLOSESOCK
  1765.                       DEBUG_W("back_wait(file is not modified): deletehttp\n");
  1766. #endif
  1767.                       deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1768.                       back[i].r=cache_read(opt,cache,back[i].url_adr,back[i].url_fil,back[i].url_sav);
  1769.                       if (!back[i].r.location)
  1770.                         back[i].r.location=back[i].location_buffer;
  1771.                       else {        /* recopier */
  1772.                         strcpy(back[i].location_buffer,back[i].r.location);
  1773.                         back[i].r.location=back[i].location_buffer;
  1774.                       }
  1775.  
  1776.                       // hack:
  1777.                       // In case of 'if-unmodified-since' hack, a 304 status can be sent
  1778.                       // then, force 'ok' status
  1779.                       if (back[i].r.statuscode == -1) {
  1780.                         if (fexist(back[i].url_sav)) {
  1781.                           back[i].r.statuscode=200;     // OK
  1782.                           if ((opt->debug>0) && (opt->log!=NULL)) {
  1783.                             fspc(opt->log,"debug"); fprintf(opt->log,"Not-modified status without cache guessed: %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  1784.                           }
  1785.                         }
  1786.                       }
  1787.  
  1788.                       // Status is okay?
  1789.                       if (back[i].r.statuscode!=-1) { // pas d'erreur de lecture
  1790.                         back[i].status=0;         // OK prΩt
  1791.                         back[i].r.notmodified=1;  // NON modifiΘ!
  1792.                         if ((opt->debug>0) && (opt->log!=NULL)) {
  1793.                           fspc(opt->log,"debug"); fprintf(opt->log,"File loaded after test from cache: %s%s"LF,back[i].url_adr,back[i].url_fil); test_flush;
  1794.                         }
  1795.  
  1796.                         // finalize
  1797.                         if (back[i].r.statuscode>0) {
  1798.                           back_finalize(opt,cache,back,i);
  1799.                         }
  1800.                         
  1801. #if DEBUGCA
  1802.                         printf("..document α jour aprΦs requΦte: %s%s\n",back[i].url_adr,back[i].url_fil);
  1803. #endif
  1804.                         
  1805.                         //printf(">%s status %d\n",back[p].r.contenttype,back[p].r.statuscode);
  1806.                       } else {  // erreur
  1807.                         back[i].status=0;  // terminΘ
  1808.                         //printf("erreur cache\n");
  1809.                         
  1810.                       } 
  1811.                       
  1812.                     } else if ((back[i].r.statuscode==301)
  1813.                       || (back[i].r.statuscode==302)
  1814.                       || (back[i].r.statuscode==303)
  1815.                       || (back[i].r.statuscode==307)
  1816.                       || (back[i].r.statuscode==412)
  1817.                       || (back[i].r.statuscode==416)
  1818.                       ) {   // Ne pas prendre le html, erreurs connues et gΘrΘes
  1819. #if HTS_DEBUG_CLOSESOCK
  1820.                       DEBUG_W("back_wait(301,302,303,307,412,416..): deletehttp\n");
  1821. #endif
  1822.                       // Couper connexion
  1823.                       deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1824.                       back[i].status=0;  // terminΘ
  1825.                       // finalize
  1826.                       if (back[i].r.statuscode>0) {
  1827.                         back_finalize(opt,cache,back,i);
  1828.                       }
  1829.                     } else {    // il faut aller le chercher
  1830.                       
  1831.                       // effacer buffer (requΦte)
  1832.                       if (back[i].r.adr!=NULL) {
  1833.                         freet(back[i].r.adr);
  1834.                         back[i].r.adr=NULL;
  1835.                       }
  1836.                       back[i].r.size=0;                                 
  1837.                       
  1838.                       // traiter 206 (partial content)
  1839.                       // xxc SI CHUNK VERIFIER QUE CA MARCHE??
  1840.                       if (back[i].r.statuscode==206) {  // on nous envoie un morceau (la fin) coz une partie sur disque!
  1841.                         LLint sz=fsize(back[i].url_sav);
  1842. #if HDEBUG
  1843.                         printf("partial content: "LLintP" on disk..\n",(LLint)sz);
  1844. #endif
  1845.                         if (sz>=0) {
  1846.                           if (!is_hypertext_mime(back[i].r.contenttype)) {    // pas HTML
  1847.                             if (opt->getmode&2) {    // on peut ecrire des non html  **sinon ben euhh sera interceptΘ plus loin, donc rap sur ce qui va sortir**
  1848.                               filenote(back[i].url_sav,NULL);    // noter fichier comme connu
  1849.                               back[i].r.out=fopen(fconv(back[i].url_sav),"ab");  // append
  1850.                               if (back[i].r.out) {
  1851.                                 back[i].r.is_write=1;    // Θcrire
  1852.                                 back[i].r.size=sz;    // dΘja Θcrit
  1853.                                 back[i].r.statuscode=200;  // Forcer 'OK'
  1854.                                 if (back[i].r.totalsize>0)
  1855.                                   back[i].r.totalsize+=sz;    // plus en fait
  1856.                                 fseek(back[i].r.out,0,SEEK_END);  // α la fin
  1857. #if HDEBUG
  1858.                                 printf("continue interrupted file\n");
  1859. #endif
  1860.                               } else {    // On est dans la m**
  1861.                                 back[i].status=0;  // terminΘ (voir plus loin)
  1862.                                 strcpy(back[i].r.msg,"Can not open partial file");
  1863.                               }
  1864.                             }
  1865.                           } else {    // mΘmoire
  1866.                             FILE* fp=fopen(fconv(back[i].url_sav),"rb");
  1867.                             if (fp) {
  1868.                               LLint alloc_mem=sz + 1;
  1869.                               if (back[i].r.totalsize>0)
  1870.                                 alloc_mem+=back[i].r.totalsize;            // AJOUTER RESTANT!
  1871.                               if ( (back[i].r.adr=(char*) malloct((INTsys) alloc_mem)) ) {
  1872.                                 back[i].r.size=sz;
  1873.                                 if (back[i].r.totalsize>0)
  1874.                                   back[i].r.totalsize+=sz;    // plus en fait
  1875.                                 if (((int) fread(back[i].r.adr,1,(INTsys)sz,fp)) != sz) {
  1876.                                   back[i].status=0;  // terminΘ (voir plus loin)
  1877.                                   strcpy(back[i].r.msg,"Can not read partial file");
  1878.                                 } else {
  1879.                                   back[i].r.statuscode=200;  // Forcer 'OK'
  1880. #if HDEBUG
  1881.                                   printf("continue in mem interrupted file\n");
  1882. #endif
  1883.                                 }
  1884.                               } else {
  1885.                                 back[i].status=0;  // terminΘ (voir plus loin)
  1886.                                 strcpy(back[i].r.msg,"No memory for partial file");
  1887.                               }
  1888.                             } else {  // Argh.. 
  1889.                               back[i].status=0;  // terminΘ (voir plus loin)
  1890.                               strcpy(back[i].r.msg,"Can not open partial file");
  1891.                             }
  1892.                           }
  1893.                         } else {    // Non trouvΘ??
  1894.                           back[i].status=0;  // terminΘ (voir plus loin)
  1895.                           strcpy(back[i].r.msg,"Can not find partial file");
  1896.                         }
  1897.                         // Erreur?
  1898.                         if (back[i].status==0) {
  1899.                           if (back[i].r.soc!=INVALID_SOCKET) {
  1900. #if HTS_DEBUG_CLOSESOCK
  1901.                             DEBUG_W("back_wait(206 solve problems): deletehttp\n");
  1902. #endif
  1903.                             deletehttp(&back[i].r);
  1904.                           }
  1905.                           back[i].r.soc=INVALID_SOCKET;
  1906.                           //back[i].r.statuscode=206;  ????????
  1907.                           back[i].r.statuscode=-5;
  1908.                           if (strnotempty(back[i].r.msg))
  1909.                             strcpy(back[i].r.msg,"Error attempting to solve status 206 (partial file)");
  1910.                         }
  1911.                       }
  1912.                       
  1913.                       if (back[i].status!=0) {  // non terminΘ (erreur)
  1914.                         if (!back[i].testmode) {    // fichier normal
  1915.                           
  1916.                           if (!back[i].r.is_chunk) {    // pas de chunk
  1917.                             //if (back[i].r.http11!=2) {    // pas de chunk
  1918.                             back[i].is_chunk=0;
  1919.                             back[i].status=1;     // start body
  1920.                           } else {
  1921. #if CHUNKDEBUG==1
  1922.                             printf("chunk encoding detected %s..\n",back[i].url_fil);
  1923. #endif
  1924.                             back[i].is_chunk=1;
  1925.                             back[i].chunk_adr=NULL;
  1926.                             back[i].chunk_size=0;
  1927.                             back[i].status=98;    // start body wait chunk
  1928.                           }
  1929.                           if (back[i].rateout>0) {
  1930.                             back[i].rateout_time=time_local();  // refresh pour transfer rate
  1931.                           }
  1932. #if HDEBUG
  1933.                           printf("(buffer) start body!\n");
  1934. #endif
  1935.                         } else {     // mode test, ne pas passer en 1!!
  1936.                           back[i].status=0;    // READY
  1937. #if HTS_DEBUG_CLOSESOCK
  1938.                           DEBUG_W("back_wait(test ok): deletehttp\n");
  1939. #endif
  1940.                           deletehttp(&back[i].r); back[i].r.soc=INVALID_SOCKET;
  1941.                           if (back[i].r.statuscode==200) {
  1942.                             strcpy(back[i].r.msg,"Test: OK");
  1943.                             back[i].r.statuscode=-10;    // test rΘussi
  1944.                           }
  1945.                           else {    // test a ΘchouΘ, on ne change rien sauf que l'erreur est α titre indicatif
  1946.                             char tempo[1000];
  1947.                             strcpy(tempo,back[i].r.msg);
  1948.                             strcpy(back[i].r.msg,"Test: ");
  1949.                             strcat(back[i].r.msg,tempo);
  1950.                           }
  1951.                           
  1952.                         }
  1953.                       }
  1954.                       
  1955.                       } 
  1956.                       
  1957.                       /*}*/
  1958.                       
  1959.                   }  // si LF
  1960.                 }  // r.size>2
  1961.               }  // si == 99
  1962.               
  1963.             } // si pas d'erreurs
  1964. #if BDEBUG==1
  1965.             printf("bytes overall: %d\n",back[i].r.size);
  1966. #endif
  1967.           }  // donnΘes dispo
  1968.           
  1969.           // en cas d'erreur cl, supprimer Θventuel fichier sur disque
  1970. #if HTS_REMOVE_BAD_FILES
  1971.           if (back[i].status<0) {
  1972.             if (!back[i].testmode) {    // pas en test
  1973.               remove(back[i].url_sav);    // Θliminer fichier (endommagΘ)
  1974.               //printf("&& %s\n",back[i].url_sav);
  1975.             }
  1976.           }
  1977. #endif
  1978.  
  1979.           /* funny log for commandline users */
  1980.           //if (!opt->quiet) {  
  1981.           // petite animation
  1982.           if (opt->verbosedisplay==1) {
  1983.             if (back[i].status==0) {
  1984.               if (back[i].r.statuscode==200)
  1985.                 printf("* %s%s ("LLintP" bytes) - OK"VT_CLREOL"\r",back[i].url_adr,back[i].url_fil,back[i].r.size);
  1986.               else
  1987.                 printf("* %s%s ("LLintP" bytes) - %d"VT_CLREOL"\r",back[i].url_adr,back[i].url_fil,back[i].r.size,back[i].r.statuscode);
  1988.               fflush(stdout);
  1989.             }
  1990.           }
  1991.           //}
  1992.           
  1993.  
  1994.       } // status>0
  1995.     }  // for
  1996.     
  1997.     // vΘrifier timeouts
  1998.     if (gestion_timeout) {
  1999.       TStamp act;
  2000.       act=time_local();    // temps en secondes
  2001.       for(i=0;i<back_max;i++) {
  2002.         if (back[i].status>0) {  // rΘception/connexion/..
  2003.           if (back[i].timeout>0) {
  2004.             //printf("time check %d\n",((int) (act-back[i].timeout_refresh))-back[i].timeout);
  2005.             if (((int) (act-back[i].timeout_refresh))>=back[i].timeout) {
  2006.               if (back[i].r.soc!=INVALID_SOCKET) {
  2007. #if HTS_DEBUG_CLOSESOCK
  2008.                 DEBUG_W("back_wait(timeout): deletehttp\n");
  2009. #endif
  2010.                 deletehttp(&back[i].r);
  2011.               }
  2012.               back[i].r.soc=INVALID_SOCKET;
  2013.               back[i].r.statuscode=-2;
  2014.               if (back[i].status==100)
  2015.                 strcpy(back[i].r.msg,"Connect Time Out");
  2016.               else if (back[i].status==101)
  2017.                 strcpy(back[i].r.msg,"DNS Time Out");
  2018.               else
  2019.                 strcpy(back[i].r.msg,"Receive Time Out");
  2020.               back[i].status=0;  // terminΘ
  2021.             } else if ((back[i].rateout>0) && (back[i].status<99)) {
  2022.               if (((int) (act-back[i].rateout_time))>=HTS_WATCHRATE) {   // checker au bout de 15s
  2023.                 if ( (int) ((back[i].r.size)/(act-back[i].rateout_time)) < back[i].rateout ) {  // trop lent
  2024.                   back[i].status=0;  // terminΘ
  2025.                   if (back[i].r.soc!=INVALID_SOCKET) {
  2026. #if HTS_DEBUG_CLOSESOCK
  2027.                     DEBUG_W("back_wait(rateout): deletehttp\n");
  2028. #endif
  2029.                     deletehttp(&back[i].r);
  2030.                   }
  2031.                   back[i].r.soc=INVALID_SOCKET;
  2032.                   back[i].r.statuscode=-3;
  2033.                   strcpy(back[i].r.msg,"Transfer Rate Too Low");
  2034.                 }
  2035.               }
  2036.             }
  2037.           }
  2038.         }
  2039.       }
  2040.     }
  2041.     max_loop--;
  2042. #if HTS_ANALYSTE
  2043.     max_loop_chk++;
  2044. #endif
  2045.   } while((busy_state) && (busy_recv) && (max_loop>0));
  2046. #if HTS_ANALYSTE
  2047.   if ((!busy_recv) && (!busy_state)) {
  2048.     if (max_loop_chk>=1) {
  2049.       Sleep(10);    // un tite pause pour Θviter les lag..
  2050.     }
  2051.   }
  2052. #endif
  2053. }
  2054.  
  2055. int back_checksize(httrackp* opt,lien_back* eback,int check_only_totalsize) {
  2056.   LLint size_to_test;
  2057.   if (check_only_totalsize)
  2058.     size_to_test=eback->r.totalsize;
  2059.   else
  2060.     size_to_test=max(eback->r.totalsize,eback->r.size);
  2061.   if (size_to_test>=0) {
  2062.     
  2063.     /* Interdiction taille par le wizard? */
  2064.     if (hts_testlinksize(opt,eback->url_adr,eback->url_fil,(eback->r.totalsize+1023)/1024)==-1) {
  2065.       return 0;     /* interdit */
  2066.     }                     
  2067.     
  2068.     /* vΘrifier taille classique (heml et non html) */
  2069.     if ((istoobig(size_to_test,eback->maxfile_html,eback->maxfile_nonhtml,eback->r.contenttype))) {
  2070.       return 0;     /* interdit */
  2071.     }
  2072.   }
  2073.   return 1;
  2074. }
  2075.  
  2076.  
  2077. // octets transfΘrΘs + add
  2078. LLint back_transfered(LLint nb,lien_back* back,int back_max) {
  2079.   int i;
  2080.   // ajouter octets en instance
  2081.   for(i=0;i<back_max;i++)
  2082.     if ((back[i].status>0) && (back[i].status<99))
  2083.       nb+=back[i].r.size;
  2084.   return nb;      
  2085. }
  2086.  
  2087. // infos backing
  2088. // j: 1 afficher sockets 2 afficher autres 3 tout afficher
  2089. void back_info(lien_back* back,int i,int j,FILE* fp) {
  2090.   if (back[i].status>=0) {
  2091.     char s[256]; 
  2092.          s[0]='\0';
  2093.     back_infostr(back,i,j,s);
  2094.     strcat(s,LF);
  2095.     fprintf(fp,"%s",s);
  2096.   }
  2097. }
  2098.  
  2099. // infos backing
  2100. // j: 1 afficher sockets 2 afficher autres 3 tout afficher
  2101. void back_infostr(lien_back* back,int i,int j,char* s) {
  2102.   if (back[i].status>=0) {
  2103.     int aff=0;
  2104.     if (j & 1) {
  2105.       if (back[i].status==100) {
  2106.         strcat(s,"CONNECT ");
  2107.       } else if (back[i].status==99) {
  2108.         strcat(s,"INFOS ");
  2109.         aff=1;
  2110.       } else if (back[i].status==98) {
  2111.         strcat(s,"INFOSC");             // infos chunk
  2112.         aff=1;
  2113.       }
  2114.       else if (back[i].status>0) {
  2115. #if HTS_ANALYSTE==2
  2116.         strcat(s,"WAIT ");
  2117. #else
  2118.         strcat(s,"RECEIVE "); 
  2119. #endif
  2120.         aff=1; 
  2121.       }
  2122.     } 
  2123.     if (j & 2) {
  2124.       if (back[i].status==0) {
  2125.         switch (back[i].r.statuscode) {
  2126.         case 200:
  2127.           strcat(s,"READY ");
  2128.           aff=1;
  2129.           break;
  2130. #if HTS_ANALYSTE==2
  2131.         default:
  2132.           strcat(s,"ERROR ");
  2133.           break;
  2134. #else
  2135.         case -1:
  2136.           strcat(s,"ERROR ");
  2137.           aff=1;
  2138.           break;
  2139.         case -2:
  2140.           strcat(s,"TIMEOUT ");
  2141.           aff=1;
  2142.           break;
  2143.         case -3:
  2144.           strcat(s,"TOOSLOW ");
  2145.           aff=1;
  2146.           break;
  2147.         case 400:
  2148.           strcat(s,"BADREQUEST ");
  2149.           aff=1;
  2150.           break;
  2151.         case 401: case 403:
  2152.           strcat(s,"FORBIDDEN ");
  2153.           aff=1;
  2154.           break;
  2155.         case 404:
  2156.           strcat(s,"NOT FOUND ");
  2157.           aff=1;
  2158.           break;
  2159.         case 500:
  2160.           strcat(s,"SERVERROR ");
  2161.           aff=1;
  2162.           break;
  2163.         default:
  2164.           {
  2165.             char s2[256];
  2166.             sprintf(s2,"ERROR(%d)",back[i].r.statuscode);
  2167.             strcat(s,s2);
  2168.           }
  2169.           aff=1;
  2170. #endif
  2171.         }
  2172.       }
  2173.     }
  2174.     
  2175.     if (aff) {
  2176.       {
  2177.         char s2[256];
  2178.         sprintf(s2,"\"%s",back[i].url_adr); strcat(s,s2);
  2179.         
  2180.         if (back[i].url_fil[0]!='/') strcat(s,"/");
  2181.         sprintf(s2,"%s\" ",back[i].url_fil); strcat(s,s2);
  2182.         sprintf(s,LLintP" "LLintP" ",back[i].r.size,back[i].r.totalsize); strcat(s,s2);
  2183.       }
  2184.     }
  2185.   }
  2186. }
  2187.  
  2188. // -- backing --
  2189.  
  2190. #undef test_flush
  2191.